#! /bin/sh
# PCP QA Test No. 667
# checks basic pcp2graphite functionality
#
# Copyright (c) 2015-2019 Red Hat, Inc.
#
seq=`basename $0`
echo "QA output created by $seq"

. ./common.python

$python -c "from pcp import pmapi" >/dev/null 2>&1
[ $? -eq 0 ] || _notrun "python pcp pmapi module not installed"
which socat >/dev/null 2>&1 || _notrun "socat binary not installed"
which pcp2graphite >$seq.full 2>&1 || _notrun "pcp2graphite not installed"

port_pickled=42004
port_text=42003
$PCP_BINADM_DIR/telnet-probe -c localhost $port_pickled \
	&& _notrun "Someone already listening on graphite pickled port $port_pickled"
$PCP_BINADM_DIR/telnet-probe -c localhost $port_text \
	&& _notrun "Someone already listening on graphite text port $port_text"

$sudo rm -rf $seq.full $tmp.*
signal=$PCP_BINADM_DIR/pmsignal
status=1	# failure is the default!

trap "\$signal -s KILL \$scpid \$p2gpid > /dev/null 2>&1; rm -f $tmp.*; exit \$status" 0 1 2 3 15

# handle differences like ...
# =(lp0 vs ?(lp0 vs <(lp0 vs :lp1
# (Vpcp.sample.byte_rate vs (S'pcp.sample.byte_rate'
# (L1192055490L vs (I1192055500
# I436 vs L436L
# remove ^ttp*
#
_filter_strings()
{
    sed \
	-e 's/^.(lp./=(lp0/' \
	-e '/^(/{
s/(S'"'"'/\(V/
s/'"'"'$//
s/(I\([0-9].*\)$/(L\1L/
}' \
	-e 's/^I\([0-9][0-9]*\)$/L\1L/' \
	-e '/^ttp*/d' \
    # end
}

_latest_pickle()
{
    cat > $tmp.pickle <<EOF
import pickle
print(pickle.HIGHEST_PROTOCOL)
EOF
    $python -u - < $tmp.pickle
}

_full_stash()
{
    echo "--- pcpgraphite stdout --" >>$seq.full
    cat $tmp.p2g.out >>$seq.full
    echo "--- pcpgraphite stderr --" >>$seq.full
    cat $tmp.p2g.err >>$seq.full
    echo "--- socket cat stdout --" >>$seq.full
    cat $tmp.socat.out >>$seq.full
    echo "--- socket cat stderr --" >>$seq.full
    cat $tmp.socat.err >>$seq.full
}

ncpu=`pmprobe -v hinv.ncpu | awk '{print $3}'`
pcp2graphite="$python `which pcp2graphite`"

echo | tee -a $seq.full
echo "=== 1. pcp2graphite one-shot pickle  ===" | tee -a $seq.full
socat -u tcp-listen:$port_pickled,reuseaddr - >$tmp.socat.out 2>$tmp.socat.err &
scpid=$!
sleep 2
$pcp2graphite -p $port_pickled -t 1 hinv.ncpu >$tmp.p2g.out 2>$tmp.p2g.err &
p2gpid=$!
sleep 3
$signal $scpid $p2gpid >/dev/null 2>&1
wait
# python pickle-format 1+ is binary, and python version dependent to boot.
# but pcp2graphite now uses ascii pickle-format 0 for maximum compatibility
fgrep -q pcp.hinv.ncpu $tmp.socat.out
[ $? -eq 0 ] && echo "Found pcp.hinv.ncpu in pickled output"
_full_stash

echo "=== 2. pcp2graphite text, 2-second aligned  ===" | tee -a $seq.full
rm -f $tmp.socat.out $tmp.socat.err
socat -u tcp-listen:$port_text,reuseaddr,fork - >>$tmp.socat.out 2>>$tmp.socat.err &
scpid=$!
sleep 2
$pcp2graphite -r -t 2 -A 2s -E $port_text -x foobar. hinv.ncpu sample.datasize >$tmp.p2g.out 2>$tmp.p2g.err &
p2gpid=$!
sleep 10 # 5sec startup + 5sec ... enough for at least 2 messages
$signal $scpid $p2gpid >/dev/null 2>&1
wait
egrep 'foobar\.hinv\.ncpu|foobar\.sample\.datasize' $tmp.socat.out \
    | head -2 \
    | sed -e "s,\.ncpu $ncpu ,.ncpu NCPUS ," |    # confirm ncpus value
    sed -r -e 's, [0-9]+[02468]$, TIMESTAMP2,'  # confirm time alignment
grep 'Excluding' $tmp.p2g.err
_full_stash

echo "=== 2a. pcp2graphite text, 2-second aligned, local  ===" | tee -a $seq.full
rm -f $tmp.socat.out $tmp.socat.err
socat -u tcp-listen:$port_text,reuseaddr,fork - >>$tmp.socat.out 2>>$tmp.socat.err &
scpid=$!
sleep 2
$pcp2graphite -r -t 2 -A 2s -E $port_text -x foobar. -L hinv.ncpu >$tmp.p2g.out 2>$tmp.p2g.err &
p2gpid=$!
sleep 10 # 5sec startup + 5sec ... enough for at least 2 messages
$signal $scpid $p2gpid >/dev/null 2>&1
wait
grep 'foobar\.hinv\.ncpu' $tmp.socat.out \
    | head -2 \
    | sed -e "s,\.ncpu $ncpu ,.ncpu NCPUS ," |    # confirm ncpus value
    sed -r -e 's, [0-9]+[02468]$, TIMESTAMP2,'  # confirm time alignment
grep 'Excluding' $tmp.p2g.err
_full_stash

echo "=== 3. pcp2graphite bad-instance tolerance ===" | tee -a $seq.full
rm -f $tmp.socat.out $tmp.socat.err
socat tcp-listen:$port_text,reuseaddr,fork - >>$tmp.socat.out 2>>$tmp.socat.err &
scpid=$!
sleep 2
$pcp2graphite -r -t 2 -A 2s -E $port_text -I sample.aggregate.null sample.string.hullo sample.bad >$tmp.p2g.out 2>$tmp.p2g.err &
p2gpid=$!
sleep 10 # 5sec startup + 5sec ... enough for at least 2 messages
$signal $scpid $p2gpid >/dev/null 2>&1
wait
# confirm time alignment
grep 'pcp\.sample\.string\.hullo' $tmp.socat.out \
    | head -10 \
    | sed -r -e 's, [0-9]+[02468]$, TIMESTAMP2,'  \
    | LC_COLLATE=POSIX sort
grep 'Excluding' $tmp.p2g.err
_full_stash

echo "=== 4. pcp2graphite count-limited archive transcription ===" | tee -a $seq.full
rm -f $tmp.socat.out $tmp.socat.err
socat -u tcp-listen:$port_text,reuseaddr,fork - >>$tmp.socat.out 2>>$tmp.socat.err &
scpid=$!
sleep 2
# TZ=UTC here to constrain pcp2graphite's -DAPPL0 stdout logging of time.ctime()
TZ=UTC $pcp2graphite -DAPPL0 -r -t 1 -s 30 -E $port_text -a archives/chartqa1.meta sample.byte_rate >$tmp.p2g.out 2>$tmp.p2g.err
$signal $scpid >/dev/null 2>&1
wait
cat $tmp.socat.out
echo
cat $tmp.p2g.out
_full_stash

echo "=== 5. pcp2graphite time-limited archive transcription ===" | tee -a $seq.full
rm -f $tmp.socat.out $tmp.socat.err
socat -u tcp-listen:$port_pickled,reuseaddr,fork - >>$tmp.socat.out 2>>$tmp.socat.err &
scpid=$!
sleep 2
TZ=UTC $pcp2graphite -DAPPL0 -r -t 1 -O '2007-10-10 22:31:30 GMT' -T '2007-10-10 22:31:40 GMT' -p $port_pickled -a archives/chartqa1.meta sample.byte_rate >$tmp.p2g.out 2>$tmp.p2g.err
$signal $scpid >/dev/null 2>&1
wait
# while pickle format 0 is ascii, it's wrapped in a struct.pack that
# puts some non-ascii goo in; we don't want that literally included in
# the .out file ... strings(1) is our friend
#
strings $tmp.socat.out | _filter_strings
echo
cat $tmp.p2g.out
_full_stash

echo | tee -a $seq.full
echo "=== 6. pcp2graphite and latest pickle version ===" | tee -a $seq.full
pickle_version=`_latest_pickle`
echo pickle version: $pickle_version >> $seq.full
socat -u tcp-listen:$port_pickled,reuseaddr - >$tmp.socat.out 2>$tmp.socat.err &
scpid=$!
sleep 2
$pcp2graphite -p $port_pickled -X $pickle_version -r -t 1 hinv.ncpu >$tmp.p2g.out 2>$tmp.p2g.err &
p2gpid=$!
sleep 3
$signal $scpid $p2gpid >/dev/null 2>&1
wait
# use same case 1 above approach for detecting something relevant
# in the pickled output, and assume we have a successful transfer
fgrep -q pcp.hinv.ncpu $tmp.socat.out
[ $? -eq 0 ] && echo "Found pcp.hinv.ncpu in highest versioned pickled output"
_full_stash

status=0
exit
